#include "DatabaseConnection.h"

#include <QStringList>
#include <QDebug>
#include <QApplication>
#include <QSqlQuery>
#include <QSqlError>

#include "Profile.h"
#include "ProfileLoggerDatabase.h"
#include "ProfileLogger.h"
#include "SqlFactory.h"

#include "Database.h"
#include "Schema.h"
#include "Table.h"
#include "Sequence.h"
#include "TableColumn.h"
#include "PrimaryKey.h"
#include "UniqueConstraint.h"
#include "TextNotEmptyCheckConstraint.h"

DatabaseConnection::DatabaseConnection(QObject* p)
  : QObject(p) 
{
}

DatabaseConnection::~DatabaseConnection()
{
  close();
}

bool DatabaseConnection::open(Project* p, const QString& fileName) {
  _db = QSqlDatabase::addDatabase("QSQLITE");
  _db.setDatabaseName(fileName);
  _db.open();

  if (!_db.database(fileName).isOpen()) {
    qDebug() << _db.lastError().text();
    return false;
  }

  QStringList tables = _db.tables();

  if (tables.size() <= 0) {
    qDebug() << "creating content...";
    ProfileLoggerDatabase* _db = (static_cast<ProfileLogger*>(QApplication::instance()))->getDatabaseModel();

    SqlFactory f(this);

    QStringList crebas;

    crebas << f.make(_db);

    for (QList<Schema*>::iterator sit = _db->getFirstSchema(); sit != _db->getLastSchema(); sit++) {
      Schema* schema = *sit;
      crebas << f.make(schema);

      for (QList<Sequence*>::iterator seqIt = schema->getFirstSequence(); seqIt != schema->getLastSequence(); seqIt++) {
	Sequence* seq = *seqIt;
	crebas << f.make(seq);
      }

      for (QList<Table*>::iterator tit = schema->getFirstTable(); tit != schema->getLastTable(); tit++) {
	Table* t = *tit;
	crebas << f.make(t);
      }
    }

    for (QList<Schema*>::iterator sit = _db->getFirstSchema(); sit != _db->getLastSchema(); sit++) {
      Schema* schema = *sit;

      for (QList<Table*>::iterator tit = schema->getFirstTable(); tit != schema->getLastTable(); tit++) {
	Table* t = *tit;

	if (t->hasPrimaryKey()) {
	  crebas << f.make(t->getPrimaryKey());
	}

	for (QList<UniqueConstraint*>::iterator uit = t->getFirstUniqueConstraint(); uit != t->getLastUniqueConstraint(); uit++) {
	  UniqueConstraint* c = *uit;
	  crebas << f.make(c);
	}

	for (QList<TextNotEmptyCheckConstraint*>::iterator uit = t->getFirstTextNotEmptyCheckConstraint(); uit != t->getLastTextNotEmptyCheckConstraint(); uit++) {
	  TextNotEmptyCheckConstraint* c = *uit;
	  crebas << f.make(c);
	}

	for (QList<ForeignKey*>::iterator fit = t->getFirstForeignKey(); fit != t->getLastForeignKey(); fit++) {
	  ForeignKey* fk = *fit;
	  crebas << f.make(fk);
	}
      }
    }

    execDDL(crebas);
  }

    return loadProject(p);
}

void DatabaseConnection::close() {
  _db.close();
}

bool DatabaseConnection::loadProject(Project* p) {
  (void) p;

  return true;
}

bool DatabaseConnection::save(Project* p) {
  (void) p;
  return true;
}

void DatabaseConnection::execDDL(QStringList l) {
  QSqlQuery q(_db);


  for (QStringList::iterator it = l.begin(); it != l.end(); it++) {
    qDebug() << "executing: " << *it;
    q.exec(*it);
  }
}
